bitkeeper revision 1.1389.2.2 (42714ca83Gv7CX98R4gC0TU3w-pX1Q)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Thu, 28 Apr 2005 20:50:48 +0000 (20:50 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Thu, 28 Apr 2005 20:50:48 +0000 (20:50 +0000)
Merge xen-2.0-testing "sync w/ unstable" changes.

.rootkeys
linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c [new file with mode: 0644]
linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h [new file with mode: 0644]

index bfec96410895376ccf58aa15483d05d54ff1f9b1..701263e1f8c36e0360907f02f6c64507347d425b 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.11-xen-sparse/arch/xen/kernel/devmem.c
 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c
 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.11-xen-sparse/arch/xen/kernel/fixup.c
+412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c
 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c
 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.11-xen-sparse/arch/xen/kernel/skbuff.c
 418f90e4lGdeJK9rmbOB1kN-IKSjsQ linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c
 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.11-xen-sparse/include/asm-xen/ctrl_if.h
 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.11-xen-sparse/include/asm-xen/evtchn.h
 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.11-xen-sparse/include/asm-xen/foreign_page.h
+412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h
 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h
 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h
 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.11-xen-sparse/include/asm-xen/linux-public/suspend.h
diff --git a/linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c b/linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c
new file mode 100644 (file)
index 0000000..0ae2ac6
--- /dev/null
@@ -0,0 +1,391 @@
+/******************************************************************************
+ * gnttab.c
+ * 
+ * Two sets of functionality:
+ * 1. Granting foreign access to our memory reservation.
+ * 2. Accessing others' memory reservations via grant references.
+ * (i.e., mechanisms for both sender and recipient of grant references)
+ * 
+ * Copyright (c) 2005, Christopher Clark
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#include <asm/uaccess.h>
+#include <asm-xen/xen_proc.h>
+#include <asm-xen/linux-public/privcmd.h>
+#include <asm-xen/gnttab.h>
+
+#ifndef set_fixmap_ma
+#define set_fixmap_ma set_fixmap
+#endif
+
+#if 1
+#define ASSERT(_p) \
+    if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
+    #_p , __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p) ((void)0)
+#endif
+
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "xen_grant: " fmt, ##args)
+
+
+EXPORT_SYMBOL(gnttab_grant_foreign_access);
+EXPORT_SYMBOL(gnttab_end_foreign_access);
+EXPORT_SYMBOL(gnttab_query_foreign_access);
+EXPORT_SYMBOL(gnttab_grant_foreign_transfer);
+EXPORT_SYMBOL(gnttab_end_foreign_transfer);
+EXPORT_SYMBOL(gnttab_alloc_grant_references);
+EXPORT_SYMBOL(gnttab_free_grant_references);
+EXPORT_SYMBOL(gnttab_claim_grant_reference);
+EXPORT_SYMBOL(gnttab_release_grant_reference);
+EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
+EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
+
+static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES];
+static grant_ref_t gnttab_free_head;
+
+static grant_entry_t *shared;
+
+/*
+ * Lock-free grant-entry allocator
+ */
+
+static inline int
+get_free_entry(
+    void)
+{
+    grant_ref_t fh, nfh = gnttab_free_head;
+    do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; }
+    while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh,
+                                    gnttab_free_list[fh])) != fh) );
+    return fh;
+}
+
+static inline void
+put_free_entry(
+    grant_ref_t ref)
+{
+    grant_ref_t fh, nfh = gnttab_free_head;
+    do { gnttab_free_list[ref] = fh = nfh; wmb(); }
+    while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
+}
+
+/*
+ * Public grant-issuing interface functions
+ */
+
+int
+gnttab_grant_foreign_access(
+    domid_t domid, unsigned long frame, int readonly)
+{
+    int ref;
+    
+    if ( unlikely((ref = get_free_entry()) == -1) )
+        return -ENOSPC;
+
+    shared[ref].frame = frame;
+    shared[ref].domid = domid;
+    wmb();
+    shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+
+    return ref;
+}
+
+void
+gnttab_grant_foreign_access_ref(
+    grant_ref_t ref, domid_t domid, unsigned long frame, int readonly)
+{
+    shared[ref].frame = frame;
+    shared[ref].domid = domid;
+    wmb();
+    shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+}
+
+
+int
+gnttab_query_foreign_access( grant_ref_t ref )
+{
+    u16 nflags;
+
+    nflags = shared[ref].flags;
+
+    return ( nflags & (GTF_reading|GTF_writing) );
+}
+
+void
+gnttab_end_foreign_access( grant_ref_t ref, int readonly )
+{
+    u16 flags, nflags;
+
+    nflags = shared[ref].flags;
+    do {
+        if ( (flags = nflags) & (GTF_reading|GTF_writing) )
+            printk(KERN_ALERT "WARNING: g.e. still in use!\n");
+    }
+    while ( (nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags );
+
+    put_free_entry(ref);
+}
+
+int
+gnttab_grant_foreign_transfer(
+    domid_t domid, unsigned long pfn )
+{
+    int ref;
+
+    if ( unlikely((ref = get_free_entry()) == -1) )
+        return -ENOSPC;
+
+    shared[ref].frame = pfn;
+    shared[ref].domid = domid;
+    wmb();
+    shared[ref].flags = GTF_accept_transfer;
+
+    return ref;
+}
+
+void
+gnttab_grant_foreign_transfer_ref(
+    grant_ref_t ref, domid_t domid, unsigned long pfn )
+{
+    shared[ref].frame = pfn;
+    shared[ref].domid = domid;
+    wmb();
+    shared[ref].flags = GTF_accept_transfer;
+}
+
+unsigned long
+gnttab_end_foreign_transfer(
+    grant_ref_t ref)
+{
+    unsigned long frame = 0;
+    u16           flags;
+
+    flags = shared[ref].flags;
+    ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
+
+    /*
+     * If a transfer is committed then wait for the frame address to appear.
+     * Otherwise invalidate the grant entry against future use.
+     */
+    if ( likely(flags != GTF_accept_transfer) ||
+         (cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
+        while ( unlikely((frame = shared[ref].frame) == 0) )
+            cpu_relax();
+
+    put_free_entry(ref);
+
+    return frame;
+}
+
+void
+gnttab_free_grant_references( u16 count, grant_ref_t head )
+{
+    /* TODO: O(N)...? */
+    grant_ref_t to_die = 0, next = head;
+    int i;
+
+    for ( i = 0; i < count; i++ )
+        to_die = next;
+        next = gnttab_free_list[next];
+        put_free_entry( to_die );
+}
+
+int
+gnttab_alloc_grant_references( u16 count,
+                               grant_ref_t *head,
+                               grant_ref_t *terminal )
+{
+    int i;
+    grant_ref_t h = gnttab_free_head;
+
+    for ( i = 0; i < count; i++ )
+        if ( unlikely(get_free_entry() == -1) )
+            goto not_enough_refs;
+
+    *head = h;
+    *terminal = gnttab_free_head;
+
+    return 0;
+
+not_enough_refs:
+    gnttab_free_head = h;
+    return -ENOSPC;
+}
+
+int
+gnttab_claim_grant_reference( grant_ref_t *private_head,
+                              grant_ref_t  terminal )
+{
+    grant_ref_t g;
+    if ( unlikely((g = *private_head) == terminal) )
+        return -ENOSPC;
+    *private_head = gnttab_free_list[g];
+    return g;
+}
+
+void
+gnttab_release_grant_reference( grant_ref_t *private_head,
+                                grant_ref_t  release )
+{
+    gnttab_free_list[release] = *private_head;
+    *private_head = release;
+}
+
+/*
+ * ProcFS operations
+ */
+
+#ifdef CONFIG_PROC_FS
+
+static struct proc_dir_entry *grant_pde;
+
+static int grant_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long data)
+{
+    int                     ret;
+    privcmd_hypercall_t     hypercall;
+
+    /* XXX Need safety checks here if using for anything other
+     *     than debugging */
+    return -ENOSYS;
+
+    if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
+        return -ENOSYS;
+
+    if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
+        return -EFAULT;
+
+    if ( hypercall.op != __HYPERVISOR_grant_table_op )
+        return -ENOSYS;
+
+    /* hypercall-invoking asm taken from privcmd.c */
+    __asm__ __volatile__ (
+        "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
+        "movl  4(%%eax),%%ebx ;"
+        "movl  8(%%eax),%%ecx ;"
+        "movl 12(%%eax),%%edx ;"
+        "movl 16(%%eax),%%esi ;"
+        "movl 20(%%eax),%%edi ;"
+        "movl   (%%eax),%%eax ;"
+        TRAP_INSTR "; "
+        "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
+        : "=a" (ret) : "0" (&hypercall) : "memory" );
+
+    return ret;
+}
+
+static struct file_operations grant_file_ops = {
+    ioctl:  grant_ioctl,
+};
+
+static int grant_read(char *page, char **start, off_t off,
+                      int count, int *eof, void *data)
+{
+    int             len;
+    unsigned int    i;
+    grant_entry_t  *gt;
+
+    gt = (grant_entry_t *)shared;
+    len = 0;
+
+    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
+        /* TODO: safety catch here until this can handle >PAGE_SIZE output */
+        if (len > (PAGE_SIZE - 200))
+        {
+            len += sprintf( page + len, "Truncated.\n");
+            break;
+        }
+
+        if ( gt[i].flags )
+            len += sprintf( page + len,
+                    "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", 
+                    i,
+                    gt[i].flags,
+                    gt[i].domid,
+                    gt[i].frame );
+
+    *eof = 1;
+    return len;
+}
+
+static int grant_write(struct file *file, const char __user *buffer,
+                       unsigned long count, void *data)
+{
+    /* TODO: implement this */
+    return -ENOSYS;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+int gnttab_resume(void)
+{
+    gnttab_setup_table_t setup;
+    unsigned long        frames[NR_GRANT_FRAMES];
+    int                  i;
+
+    setup.dom        = DOMID_SELF;
+    setup.nr_frames  = NR_GRANT_FRAMES;
+    setup.frame_list = frames;
+
+    BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0);
+    BUG_ON(setup.status != 0);
+
+    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
+        set_fixmap_ma(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
+
+    return 0;
+}
+
+int gnttab_suspend(void)
+{
+    int i;
+
+    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
+       clear_fixmap(FIX_GNTTAB_END - i);
+
+    return 0;
+}
+
+static int __init gnttab_init(void)
+{
+    int i;
+
+    BUG_ON(gnttab_resume());
+
+    shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
+
+    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
+        gnttab_free_list[i] = i + 1;
+    
+#ifdef CONFIG_PROC_FS
+    /*
+     *  /proc/xen/grant : used by libxc to access grant tables
+     */
+    if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
+    {
+        WPRINTK("Unable to create grant xen proc entry\n");
+        return -1;
+    }
+
+    grant_file_ops.read   = grant_pde->proc_fops->read;
+    grant_file_ops.write  = grant_pde->proc_fops->write;
+
+    grant_pde->proc_fops  = &grant_file_ops;
+
+    grant_pde->read_proc  = &grant_read;
+    grant_pde->write_proc = &grant_write;
+#endif
+
+    printk("Grant table initialized\n");
+    return 0;
+}
+
+__initcall(gnttab_init);
diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h b/linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h
new file mode 100644 (file)
index 0000000..642a74d
--- /dev/null
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * gnttab.h
+ * 
+ * Two sets of functionality:
+ * 1. Granting foreign access to our memory reservation.
+ * 2. Accessing others' memory reservations via grant references.
+ * (i.e., mechanisms for both sender and recipient of grant references)
+ * 
+ * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2005, Christopher Clark
+ */
+
+#ifndef __ASM_GNTTAB_H__
+#define __ASM_GNTTAB_H__
+
+#include <linux/config.h>
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xen-public/grant_table.h>
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#define NR_GRANT_FRAMES 4
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+
+int
+gnttab_grant_foreign_access(
+    domid_t domid, unsigned long frame, int readonly);
+
+void
+gnttab_end_foreign_access(
+    grant_ref_t ref, int readonly);
+
+int
+gnttab_grant_foreign_transfer(
+    domid_t domid, unsigned long pfn);
+
+unsigned long
+gnttab_end_foreign_transfer(
+    grant_ref_t ref);
+
+int
+gnttab_query_foreign_access( 
+    grant_ref_t ref );
+
+/*
+ * operations on reserved batches of grant references
+ */
+int
+gnttab_alloc_grant_references(
+    u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal );
+
+void
+gnttab_free_grant_references(
+    u16 count, grant_ref_t private_head );
+
+int
+gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal
+);
+
+void
+gnttab_release_grant_reference(
+    grant_ref_t *private_head, grant_ref_t release );
+
+void
+gnttab_grant_foreign_access_ref(
+    grant_ref_t ref, domid_t domid, unsigned long frame, int readonly);
+
+void
+gnttab_grant_foreign_transfer_ref(
+    grant_ref_t, domid_t domid, unsigned long pfn);
+
+
+#endif /* __ASM_GNTTAB_H__ */